﻿#include "Util.h"
#include <QDateTime>
#include <QTextCodec>
#include <QUuid>

QTime Util::secToTime(int second)
{
	QTime time(0, 0);
	return time.addSecs(second);
}

QString Util::fileSizeString(quint64 sizeInByte)
{
	quint64 kb = (quint64)1024;
	quint64 mb = (quint64)1024 * 1024;
	quint64 gb = (quint64)1024 * 1024 * 1024;
	quint64 tb = (quint64)1024 * 1024 * 1024 * 1024;

	if (sizeInByte > kb && sizeInByte <= mb)
	{
		return (QString("%1 KB").arg((double)sizeInByte / 1024, 10, 'f', 2));
	}
	else if (sizeInByte > mb && sizeInByte <= gb)
	{
		return (QString("%1 MB").arg((double)sizeInByte / (1024 * 1024), 10, 'f', 2));
	}
	else if (sizeInByte > gb && sizeInByte <= tb)
	{
		return (QString("%1 GB").arg((double)sizeInByte / (1024 * 1024 * 1024), 10, 'f', 2));
	}
	else if (sizeInByte > tb)
	{
		return (QString("%1 TB").arg((double)sizeInByte / tb, 10, 'f', 2));
	} 
	else
	{
		return (QString("%1 Byte").arg((double)sizeInByte, 10, 'f', 2));
	}
}

QString Util::getUid()
{
	QString ret = QUuid::createUuid().toString();
	ret.remove("{");
	ret.remove("}");
	ret.remove("-");
	return ret;
}

QList<Vector3D> Util::sectionLinearInterpolation(const Vector3D &first, const Vector3D &last, int count)
{
	QList<Vector3D> ret;

	if (abs(first.x() - last.x()) < 0.0000001) // 经度相同
	{
		double Δy = (last.y() - first.y()) / count;
		double Δz = (last.z() - first.z()) / count;
		for (int i = 0; i < count; ++i)
		{
			ret.push_back(Vector3D(first.x(), first.y() + i * Δy, first.z() + i * Δz));
		}
	}
	else
	{
		for (int k = 0; k < count; ++k)
		{
			double x1 = first.x();
			double x2 = last.x();
			double y1 = first.y();
			double y2 = last.y();
			double z1 = first.z();
			double z2 = last.z();

			double xk = x1 + (x2 - x1) * k / count;
			double yk = (xk - x2) / (x1 - x2) * y1 + (xk - x1) / (x2 - x1) * y2;
			double zk = (xk - x2) / (x1 - x2) * z1 + (xk - x1) / (x2 - x1) * z2;

			ret.push_back(Vector3D(xk, yk, zk));
		}
	}
	return ret;
}

double Util::LoLaDmsToDec(int degree, int minute, int second)
{
    return degree + (minute + second / 60.0) / 60.0;
}

void Util::LoLaDecToDms(int& degree, int& minute, int& second, double decimal)
{
    degree = (int)decimal;
    double tmpMinute = (decimal - degree) * 60;
    minute = (int)tmpMinute;
    second = (tmpMinute - minute) * 60;
}

QString Util::LoDecToDmsText(double longitude)
{
    char ewChar = (longitude >= 0) ? 'E' : 'W';

    longitude = abs(longitude);

    int degree = 0;
    int minute = 0;
    int second = 0;

    LoLaDecToDms(degree, minute, second, longitude);


    return QString("%1%2%3").arg(degree, 3, 10, QChar('0'))
        .arg(minute, 2, 10, QChar('0'))
        .arg(second, 2, 10, QChar('0'))
        + ewChar;
}

QString Util::LaDecToDmsText(double latitude)
{
    char nsChar = (latitude >= 0) ? 'N' : 'S';

    latitude = abs(latitude);

    int degree = 0;
    int minute = 0;
    int second = 0;

    LoLaDecToDms(degree, minute, second, latitude);


    return QString("%1%2%3").arg(degree, 2, 10, QChar('0'))
        .arg(minute, 2, 10, QChar('0'))
        .arg(second, 2, 10, QChar('0'))
        + nsChar;
}

QString Util::LoLaDecToDmsText(double longitude, double latitude)
{
    return LaDecToDmsText(latitude) + LoDecToDmsText(longitude);
}

bool Util::LoLaDecFromDmsText(double& decimal, const QString& dmsStr)
{
    if (dmsStr.isEmpty())
    {
        decimal = 0;
        return true;
    }

    int numSigned = 0;
    QChar lastChar = dmsStr.at(dmsStr.length() - 1);
    if ('N' == lastChar || 'E' == lastChar)
    {
        numSigned = 1;
    }
    else if ('S' == lastChar || 'W' == lastChar)
    {
        numSigned = -1;
    }
    else
    {
        return false;
    }

    int degree = dmsStr.mid(0, dmsStr.size() - 5).toInt();
    int minute = dmsStr.mid(dmsStr.size() - 5, 2).toInt();
    int second = dmsStr.mid(dmsStr.size() - 3, 2).toInt();

    decimal = LoLaDmsToDec(degree, minute, second) * numSigned;
    return true;
}

bool Util::LoLaDecFromDmsText(double& longitude, double& latitude, const QString& dmsStr)
{
    int indexN = dmsStr.indexOf('N');
    int indexS = dmsStr.indexOf('S');
    if (-1 == indexN && -1 == indexS)
    {
        return false;
    }

    int indexLoLast = (-1 != indexN) ? indexN : indexS;

    if (!LoLaDecFromDmsText(latitude, dmsStr.mid(0, indexLoLast + 1)))
    {
        return false;
    }

    if (!LoLaDecFromDmsText(longitude, dmsStr.mid(indexLoLast + 1)))
    {
        return false;
    }

    return true;
}

QString Util::timeToHhmmssStr(quint64 time)
{
    return QString("%1:%2:%3").arg(time / 3600, 2, 10, QChar('0'))
        .arg(time / 60 % 60, 2, 10, QChar('0')).arg(time % 60, 2, 10, QChar('0'));
}

quint64 Util::timeFromHhmmssStr(const QString& timeStr)
{
    QStringList hhMmSsStrList = timeStr.split(":");
    if (3 != hhMmSsStrList.size())
    {
        return 0;
    }

    return hhMmSsStrList.at(0).toULong() * 3600 + hhMmSsStrList.at(1).toULong() * 60 + hhMmSsStrList.at(2).toULong();
}

bool Util::meterFromMeterFootStr(double& meter, const QString& strMeterFoot)
{
    int indexMeter = strMeterFoot.indexOf(QStringLiteral("/"));

    if (indexMeter < 0)
    {
        meter = 0;
        return false;
    }

    meter = strMeterFoot.mid(0, indexMeter).toDouble();

    return true;
}

int Util::subSystemCodeFromLogicId(quint32 logicId)
{
	int ret = (logicId & 0xFFFF0000) >> 16;
	return ret;
}

int Util::softwareIdFromLogicId(quint32 logicId)
{
	int ret = (logicId & 0x0000FF00) >> 8;
	return ret;
}

QString Util::toHex(quint64 number)
{
	return QString("0x%1").arg(QString::number(number, 16).toUpper());
}

QDateTime Util::secondToDateTime(quint64 second)
{
	return QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0)).addSecs(second);
}

int Util::colorToARGB(const QColor &color)
{
	int ret = 0;
	auto c = color.toRgb();
	ret = ret | color.alpha();
	ret = (ret << 8) | color.red();
	ret = (ret << 8) | color.green();
	ret = (ret << 8) | color.blue();
	return ret;
}

quint64 Util::dateTimeToSecond(const QDateTime &dateTime)
{
	return QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0)).secsTo(dateTime);
}
